package com.pfzy.utildemo.activity.local;

import android.Manifest;
import android.annotation.TargetApi;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.Settings;
import android.text.TextUtils;
import android.view.View;
import android.widget.RadioGroup;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

import com.amap.api.location.AMapLocation;
import com.amap.api.location.AMapLocationClient;
import com.amap.api.location.AMapLocationClientOption;
import com.amap.api.location.AMapLocationListener;
import com.amap.api.location.AMapLocationQualityReport;
import com.pfzy.utildemo.R;
import com.pfzy.utildemo.activity.base.BaseActivity;
import com.pfzy.lib.config.log.MyLog;
import com.pfzy.utildemo.databinding.ActivityLocalBinding;
import com.pfzy.utildemo.utils.NotificationUtils;

import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

/**
 * 华为
 * 融合定位开发
 * https://developer.huawei.com/consumer/cn/doc/HMSCore-Guides/location-develop-steps-0000001050746143
 */
public class LocalActivity extends BaseActivity implements View.OnClickListener, RadioGroup.OnCheckedChangeListener {
    private ActivityLocalBinding mBind;
    private Intent serviceIntent = null;
    private AMapLocationClient locationClient = null;
    private AMapLocationClientOption locationOption = null;
    private int LOCATION_TYPE_ENABLE_BACKGROUND = 0;
    private int LOCATION_TYPE_FORCEGROUND_SERVICE = 1;
    private int locationType = LOCATION_TYPE_ENABLE_BACKGROUND;
    boolean isSartLocation = false;

    /**
     * 需要进行检测的权限数组
     */
    protected String[] needPermissions = {
            Manifest.permission.ACCESS_COARSE_LOCATION,
            Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.WRITE_EXTERNAL_STORAGE,
            Manifest.permission.READ_EXTERNAL_STORAGE,
            Manifest.permission.READ_PHONE_STATE
    };
    private static final int PERMISSON_REQUESTCODE = 0;

    /**
     * 定位监听
     */
    AMapLocationListener locationListener = new AMapLocationListener() {
        @Override
        public void onLocationChanged(AMapLocation location) {
            if (null != location) {
                StringBuffer sb = new StringBuffer();
                // errCode等于0代表定位成功，其他的为定位失败，具体的可以参照官网定位错误码说明
                if (location.getErrorCode() == 0) {
                    sb.append("定位成功" + "\n");
                    sb.append("定位类型: " + location.getLocationType() + "\n");
                    sb.append("经    度    : " + location.getLongitude() + "\n");
                    sb.append("纬    度    : " + location.getLatitude() + "\n");
                    sb.append("精    度    : " + location.getAccuracy() + "米" + "\n");
                    sb.append("提供者    : " + location.getProvider() + "\n");

                    sb.append("速    度    : " + location.getSpeed() + "米/秒" + "\n");
                    sb.append("角    度    : " + location.getBearing() + "\n");
                    // 获取当前提供定位服务的卫星个数
                    sb.append("星    数    : " + location.getSatellites() + "\n");
                    sb.append("国    家    : " + location.getCountry() + "\n");
                    sb.append("省            : " + location.getProvince() + "\n");
                    sb.append("市            : " + location.getCity() + "\n");
                    sb.append("城市编码 : " + location.getCityCode() + "\n");
                    sb.append("区            : " + location.getDistrict() + "\n");
                    sb.append("区域 码   : " + location.getAdCode() + "\n");
                    sb.append("地    址    : " + location.getAddress() + "\n");
                    sb.append("兴趣点    : " + location.getPoiName() + "\n");

                    // 定位完成的时间
                    sb.append("定位时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(location.getTime()) + "\n");
                } else {
                    // 定位失败
                    sb.append("定位失败" + "\n");
                    sb.append("错误码:" + location.getErrorCode() + "\n");
                    sb.append("错误信息:" + location.getErrorInfo() + "\n");
                    sb.append("错误描述:" + location.getLocationDetail() + "\n");
                }
                sb.append("***定位质量报告***").append("\n");
                sb.append("* WIFI开关：").append(location.getLocationQualityReport().isWifiAble() ? "开启" : "关闭").append("\n");
                sb.append("* GPS状态：").append(getGPSStatusString(location.getLocationQualityReport().getGPSStatus())).append("\n");
                sb.append("* GPS星数：").append(location.getLocationQualityReport().getGPSSatellites()).append("\n");
                sb.append("****************").append("\n");
                // 定位之后的回调时间
                sb.append("回调时间: " + new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.CHINA).format(System.currentTimeMillis()) + "\n");

                // 解析定位结果，
                String result = sb.toString();
                mBind.localResult.setText(result);
            } else {
                mBind.localResult.setText("定位失败，loc is null");
            }
        }
    };

    @Override
    public void onCreate(Bundle bundle) {
        super.onCreate(bundle);
        mBind = ActivityLocalBinding.inflate(getLayoutInflater());
        setContentView(mBind.getRoot());

        serviceIntent = new Intent();
        serviceIntent.setClass(this, LocationForcegroundService.class);

        initView();
        //初始化定位
        initLocation();
    }

    @Override
    protected void onPause() {
        super.onPause();
        //如果已经开始定位了，显示通知栏
        if (isSartLocation) {
            if (locationType == LOCATION_TYPE_ENABLE_BACKGROUND) {
                // 开启APSService后台定位能力
                if (null != locationClient) {
                    locationClient.enableBackgroundLocation(NotificationUtils.NOTIFY_ID, NotificationUtils.buildNotification(getApplicationContext()));
                }
            } else {
                // 如果使用{@link AMapLocationClient#enableBackgroundLocation(int, Notification)}，这段代码可以不要
                if (null != serviceIntent) {
                    startService(serviceIntent);
                }
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        /**
         * 如果要一直显示可以不执行
         * 如果使用{@link AMapLocationClient#disableBackgroundLocation(boolean)} ，这段代码可以不要
         */
        if (null != serviceIntent) {
            stopService(serviceIntent);
        }

        if (locationType == LOCATION_TYPE_ENABLE_BACKGROUND) {
            // 关闭APSService后台定位能力
            if (null != locationClient) {
                locationClient.disableBackgroundLocation(true);
            }
        }
        else{

        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        destroyLocation();

        //如果要一直显示可以不执行
        if (null != serviceIntent) {
            stopService(serviceIntent);
        }
    }

    /**
     * 销毁定位
     */
    private void destroyLocation() {
        if (null != locationClient) {
            /**
             * 如果AMapLocationClient是在当前Activity实例化的，
             * 在Activity的onDestroy中一定要执行AMapLocationClient的onDestroy
             */
            locationClient.onDestroy();
            locationClient = null;
            locationOption = null;
        }
        isSartLocation = false;
    }

    private void initView() {
        mBind.localLocationMode.setOnCheckedChangeListener(this);
        mBind.localAmap.setOnClickListener(this);
        mBind.localAndroid.setOnClickListener(this);
    }

    /**
     * 初始化定位
     */
    private void initLocation() {
        // 初始化client
        try {
            locationClient = new AMapLocationClient(this.getApplicationContext());
        } catch (Exception e) {
            e.printStackTrace();
        }
        locationOption = getDefaultOption();
        // 设置定位参数
        locationClient.setLocationOption(locationOption);
        // 设置定位监听
        locationClient.setLocationListener(locationListener);
    }

    /**
     * 默认的定位参数
     */
    private AMapLocationClientOption getDefaultOption() {
        AMapLocationClientOption mOption = new AMapLocationClientOption();
        mOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);//可选，设置定位模式，可选的模式有高精度、仅设备、仅网络。默认为高精度模式
        mOption.setGpsFirst(false);//可选，设置是否gps优先，只在高精度模式下有效。默认关闭
        mOption.setHttpTimeOut(30000);//可选，设置网络请求超时时间。默认为30秒。在仅设备模式下无效
        mOption.setInterval(2000);//可选，设置定位间隔。默认为2秒
        mOption.setNeedAddress(true);//可选，设置是否返回逆地理地址信息。默认是true
        mOption.setOnceLocation(false);//可选，设置是否单次定位。默认是false
        mOption.setOnceLocationLatest(false);//可选，设置是否等待wifi刷新，默认为false.如果设置为true,会自动变为单次定位，持续定位时不要使用
        AMapLocationClientOption.setLocationProtocol(AMapLocationClientOption.AMapLocationProtocol.HTTP);//可选， 设置网络请求的协议。可选HTTP或者HTTPS。默认为HTTP
        mOption.setSensorEnable(false);//可选，设置是否使用传感器。默认是false
        mOption.setWifiScan(true); //可选，设置是否开启wifi扫描。默认为true，如果设置为false会同时停止主动刷新，停止以后完全依赖于系统刷新，定位位置可能存在误差
        mOption.setLocationCacheEnable(true); //可选，设置是否使用缓存定位，默认为true
        return mOption;
    }

    @Override
    public void onCheckedChanged(RadioGroup group, int checkedId) {
        if (null == locationOption) {
            locationOption = new AMapLocationClientOption();
        }
        switch (checkedId) {
            case R.id.local_batterySaving:
                locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Battery_Saving);
                break;
            case R.id.local_deviceSensors:
                locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Device_Sensors);
                break;
            case R.id.local_hightAccuracy:
                locationOption.setLocationMode(AMapLocationClientOption.AMapLocationMode.Hight_Accuracy);
                break;
            default:
                break;
        }
    }

    @Override
    public void onClick(View v) {
        int viewId = v.getId();
        if (viewId == R.id.local_android) {
            if (verifyPermissions(needPermissions)) {
                getLocation(this);
            } else {
                checkPermissions(needPermissions);
            }
        } else if (viewId == R.id.local_amap) {
            if (verifyPermissions(needPermissions)) {
                if (mBind.localAmap.getText().equals(getResources().getString(R.string.startLocation))) {
                    setViewEnable(false);
                    mBind.localAmap.setText(getResources().getString(R.string.stopLocation));
                    mBind.localResult.setText("正在定位...");
                    startLocation();
                } else {
                    setViewEnable(true);
                    mBind.localAmap.setText(getResources().getString(R.string.startLocation));
                    stopLocation();
                    mBind.localResult.setText("定位停止");
                }
            } else {
                checkPermissions(needPermissions);
            }
        }
    }

    private void getLocation(Context context) {
        Location location = null;
        // 获取位置管理器
        LocationManager locationManager = (LocationManager) context.getSystemService(AppCompatActivity.LOCATION_SERVICE);
        if (ActivityCompat.checkSelfPermission(
                context,
                Manifest.permission.ACCESS_FINE_LOCATION
        ) == PackageManager.PERMISSION_GRANTED
        ) {
            location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            if (location != null) {
                MyLog.logd("原生定位定位, " + location.toString());
                mBind.localResult.setText(location.toString());
            } else {
                locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000L, 0f, new LocationListener() {
                    @Override
                    public void onLocationChanged(@NonNull Location location) {
                        MyLog.logd("原生定位定位 " + location.toString());
                        mBind.localResult.setText(location.toString());
                    }
                });
            }
        }
    }

    /**
     * 获取GPS状态的字符串
     */
    private String getGPSStatusString(int statusCode) {
        String str = "";
        switch (statusCode) {
            case AMapLocationQualityReport.GPS_STATUS_OK:
                str = "GPS状态正常";
                break;
            case AMapLocationQualityReport.GPS_STATUS_NOGPSPROVIDER:
                str = "手机中没有GPS Provider，无法进行GPS定位";
                break;
            case AMapLocationQualityReport.GPS_STATUS_OFF:
                str = "GPS关闭，建议开启GPS，提高定位质量";
                break;
            case AMapLocationQualityReport.GPS_STATUS_MODE_SAVING:
                str = "选择的定位模式中不包含GPS定位，建议选择包含GPS定位的模式，提高定位质量";
                break;
            case AMapLocationQualityReport.GPS_STATUS_NOGPSPERMISSION:
                str = "没有GPS定位权限，建议开启gps定位权限";
                break;
        }
        return str;
    }

    /**
     * 设置控件的可用状态
     */
    private void setViewEnable(boolean isEnable) {
        for (int i = 0; i < mBind.localLocationMode.getChildCount(); i++) {
            mBind.localLocationMode.getChildAt(i).setEnabled(isEnable);
        }
        mBind.etInterval.setEnabled(isEnable);
        mBind.etHttpTimeout.setEnabled(isEnable);
        mBind.cbOnceLocation.setEnabled(isEnable);
        mBind.cbGpsFirst.setEnabled(isEnable);
        mBind.cbNeedAddress.setEnabled(isEnable);
        mBind.cbCacheAble.setEnabled(isEnable);
        mBind.cbOnceLastest.setEnabled(isEnable);
        mBind.cbSensorAble.setEnabled(isEnable);
    }

    /**
     * 开始定位
     */
    private void startLocation() {
        // 根据控件的选择，重新设置定位参数
        resetOption();
        // 设置定位参数
        locationClient.setLocationOption(locationOption);
        // 启动定位
        locationClient.startLocation();
        isSartLocation = true;
    }

    /**
     * 停止定位
     */
    private void stopLocation() {
        // 停止定位
        locationClient.stopLocation();
        isSartLocation = false;
    }

    // 根据控件的选择，重新设置定位参数
    private void resetOption() {
        // 设置是否需要显示地址信息
        locationOption.setNeedAddress(mBind.cbNeedAddress.isChecked());
        /**
         * 设置是否优先返回GPS定位结果，如果30秒内GPS没有返回定位结果则进行网络定位
         * 注意：只有在高精度模式下的单次定位有效，其他方式无效
         */
        locationOption.setGpsFirst(mBind.cbGpsFirst.isChecked());
        // 设置是否开启缓存
        locationOption.setLocationCacheEnable(mBind.cbCacheAble.isChecked());
        // 设置是否单次定位
        locationOption.setOnceLocation(mBind.cbOnceLocation.isChecked());
        // 设置是否等待设备wifi刷新，如果设置为true,会自动变为单次定位，持续定位时不要使用
        locationOption.setOnceLocationLatest(mBind.cbOnceLastest.isChecked());
        // 设置是否使用传感器
        locationOption.setSensorEnable(mBind.cbSensorAble.isChecked());
        // 设置是否开启wifi扫描，如果设置为false时同时会停止主动刷新，停止以后完全依赖于系统刷新，定位位置可能存在误差
        String strInterval = mBind.etInterval.getText().toString();
        if (!TextUtils.isEmpty(strInterval)) {
            try {
                // 设置发送定位请求的时间间隔,最小值为1000，如果小于1000，按照1000算
                locationOption.setInterval(Long.valueOf(strInterval));
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }

        String strTimeout = mBind.etHttpTimeout.getText().toString();
        if (!TextUtils.isEmpty(strTimeout)) {
            try {
                // 设置网络请求超时时间
                locationOption.setHttpTimeOut(Long.valueOf(strTimeout));
            } catch (Throwable e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 检测是否所有的权限都已经授权
     */
    private boolean verifyPermissions(String[] permissions) {
        for (String item : permissions) {
            if (ActivityCompat.checkSelfPermission(this, item) != PackageManager.PERMISSION_GRANTED) {
                return false;
            }
        }
        return true;
    }

    private void checkPermissions(String... permissions) {
        try {
            if (Build.VERSION.SDK_INT >= 23
                    && getApplicationInfo().targetSdkVersion >= 23) {
                List<String> needRequestPermissonList = findDeniedPermissions(permissions);
                if (null != needRequestPermissonList
                        && needRequestPermissonList.size() > 0) {
                    String[] array = needRequestPermissonList.toArray(new String[needRequestPermissonList.size()]);
                    Method method = getClass().getMethod("requestPermissions", new Class[]{String[].class, int.class});
                    method.invoke(this, array, PERMISSON_REQUESTCODE);
                }
            }
        } catch (Throwable e) {
        }
    }

    /**
     * 获取权限集中需要申请权限的列表
     */
    private List<String> findDeniedPermissions(String[] permissions) {
        List<String> needRequestPermissonList = new ArrayList<String>();
        if (Build.VERSION.SDK_INT >= 23
                && getApplicationInfo().targetSdkVersion >= 23) {
            try {
                for (String perm : permissions) {
                    Method checkSelfMethod = getClass().getMethod("checkSelfPermission", String.class);
                    Method shouldShowRequestPermissionRationaleMethod = getClass().getMethod("shouldShowRequestPermissionRationale",
                            String.class);
                    if ((Integer) checkSelfMethod.invoke(this, perm) != PackageManager.PERMISSION_GRANTED
                            || (Boolean) shouldShowRequestPermissionRationaleMethod.invoke(this, perm)) {
                        needRequestPermissonList.add(perm);
                    }
                }
            } catch (Throwable e) {

            }
        }
        return needRequestPermissonList;
    }

    @TargetApi(23)
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] paramArrayOfInt) {
        if (requestCode == PERMISSON_REQUESTCODE) {
            if (!verifyPermissions(permissions)) {
                showMissingPermissionDialog();
            }
        }
    }

    /**
     * 显示提示信息
     *
     * @since 2.5.0
     */
    private void showMissingPermissionDialog() {
        AlertDialog.Builder builder = new AlertDialog.Builder(this);
        builder.setTitle("提示");
        builder.setMessage("当前应用缺少必要权限。\\n\\n请点击\\\"设置\\\"-\\\"权限\\\"-打开所需权限。");

        // 拒绝, 退出应用
        builder.setNegativeButton("取消",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        finish();
                    }
                });

        builder.setPositiveButton("设置",
                new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        startAppSettings();
                    }
                });

        builder.setCancelable(false);
        builder.show();
    }

    /**
     * 启动应用的设置
     */
    private void startAppSettings() {
        Intent intent = new Intent(
                Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
        intent.setData(Uri.parse("package:" + getPackageName()));
        startActivity(intent);
    }
}
